package com.roger.bt.trans.ser;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;

import com.roger.bt.trans.ser.util.Logger;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class BtBase {
    private static String TAG = "Test" + BtBase.class.getSimpleName();
    static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    public static final String FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Bluetooth/";

    private static final int FLAG_MSG = 0;
    private static final int FLAG_FILE = 1;

    private Executor EXECUTOR = Executors.newCachedThreadPool();
    private BluetoothSocket mSocket;
    private DataOutputStream outStream;
    private Listener mListener;
    private boolean isRead,isSending;

    private static final Handler sHandler = new Handler();

    BtBase(Listener listener) {
        mListener = listener;
    }

    void loopRead(BluetoothSocket socket) {
        mSocket = socket;
        try {
            if (!mSocket.isConnected()) mSocket.connect();
            notifyUI(Listener.CONNECTED, mSocket.getRemoteDevice());
            outStream = new DataOutputStream(mSocket.getOutputStream());
            DataInputStream inStream = new DataInputStream(mSocket.getInputStream());
            isRead = true;
            while (isRead) {
                switch (inStream.readInt()) {
                    case FLAG_MSG:
                        String msg = inStream.readUTF();
                        notifyUI(Listener.MSG, "short message：" + msg);
                        break;
                    case FLAG_FILE:
                        mkdirs();
                        String fileName = inStream.readUTF();
                        long fileLen = inStream.readLong();
                        long len = 0;
                        int r;
                        byte[] b = new byte[1048576];
                        FileOutputStream out = new FileOutputStream(FILE_PATH + fileName,false);
                        Logger.log(FILE_PATH +"logs.txt","start receive file(" + fileName + "),please wait...");
                        Date from = new Date(System.currentTimeMillis());
                        while (len < fileLen) {
                            int size = inStream.read(b);
                            out.write(b, 0, size);
                            len += (long) size;
                            out.flush();
                        }
                        out.close();
                        Date to = new Date(System.currentTimeMillis());
                        Logger.log(FILE_PATH +"logs.txt","receive file finished");
                        Logger.log(FILE_PATH +"logs.txt","receive cost time :"+ String.valueOf(to.getTime()-from.getTime()));
                        Logger.log(FILE_PATH +"logs.txt","receive rate:"+((fileLen/1.024)/(to.getTime()-from.getTime()))+"kb/s");
                        break;
                }
            }
        } catch (Throwable e) {
            Log.d("testC","receive err");
            close();
        }
    }

    public void sendFile(final String filePath) {
        if (isSending) return;
        isSending = true;
        EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    File file = new File(filePath);
                    FileInputStream in = new FileInputStream(file);
                    outStream.writeInt(FLAG_FILE);
                    outStream.writeUTF(file.getName());
                    outStream.writeLong(file.length());
                    outStream.flush();
                    byte[] b = new byte[32768];
                    Log.d(TAG,"send file start");
                    Logger.log(FILE_PATH +"logs.txt","start send file(" + filePath + "),please wait...");
                    Date from =new Date(System.currentTimeMillis());
                    while (true){
                        int size = in.read(b, 0, 32768);
                        if (size == -1) {
                            in.close();
                            Date to =new Date(System.currentTimeMillis());
                            Log.d(TAG,"send file finished");
                            Logger.log(FILE_PATH +"logs.txt","send file finished");
                            Logger.log(FILE_PATH +"logs.txt","send cost time : "+String.valueOf(to.getTime()-from.getTime()));
                            Logger.log(FILE_PATH +"logs.txt","send rate : "+((file.length()/1.024)/(to.getTime()-from.getTime()))+"kb/s");
                            break;
                        }
                        outStream.write(b, 0, size);
                        outStream.flush();
                    }
                } catch (Throwable e) {
                    Log.d("testC","send err");
                    close();
                }
                isSending = false;
            }
        });
    }

    public void unListener() {
        mListener = null;
    }

    public void close() {
        try {
            isRead = false;
            isSending = false ;
            mSocket.close();
            notifyUI(Listener.DISCONNECTED, null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public boolean isConnected(BluetoothDevice dev) {
        boolean connected = (mSocket != null && mSocket.isConnected());
        if (dev == null) return connected;
        return connected && mSocket.getRemoteDevice().equals(dev);
    }

    private void notifyUI(final int state, final Object obj) {
        runUi(new Runnable() {
            @Override
            public void run() {
                try {
                    if (mListener != null)
                        mListener.socketNotify(state, obj);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });
    }


    private static void runUi(Runnable runnable) {
        sHandler.post(runnable);
    }

    @SuppressWarnings("ResultOfMethodCallIgnored")
    private static void mkdirs() {
        File f = new File(FILE_PATH);
        if(!f.exists())  f.mkdirs();
    }
}
